/*
 * software_i2c_master.cpp
 *
 *  Created on: Jan 11, 2014
 *      Author: bohni
 */


#include "software_i2c_master.h"


#define SCL_LOW		SCL_PORT &= ~(1<<SCL);
#define SCL_HIGH	SCL_PORT |= (1<<SCL);

#define SDA_LOW		SDA_PORT &= ~(1<<SDA);
#define SDA_HIGH	SDA_PORT |= (1<<SDA);

void sda_out(){
		SDA_PORT &= ~(1<<SDA);
		SDA_DDR |= (1<<SDA);
}

void sda_in(){

	SDA_DDR &= ~(1< SDA);
	#ifdef USE_INT_PULLUP
		SDA_PORT |= (1<<SDA);
	#endif

}

void i2c_clock() {

	SCL_LOW;
	_delay_us(TIMING_DELAY_US);
	SCL_HIGH;
	_delay_us(TIMING_DELAY_US);
}



void soft_i2c_master_init( void ) {
	SCL_DDR |= (1<<SCL);


}


uint8_t soft_i2c_start( uint8_t adr ) {

	sda_out();
	SDA_HIGH;
	SCL_HIGH;
	_delay_us(3);
	SDA_LOW;

	return soft_i2c_send_data( adr );

}


uint8_t soft_i2c_repstart( uint8_t adr ) {

	return soft_i2c_start(adr);

}


void soft_i2c_stop( void ) {

	sda_out();
	SDA_LOW;
	_delay_us(2);
	SCL_HIGH;
	_delay_us(3);
	SDA_HIGH;

}


uint8_t soft_i2c_send_data( uint8_t data ) {

	sda_out();

	for(uint8_t i=0; i<8; i++) {
		if (data & 0x80) {
			SDA_HIGH;
		} else {
			SDA_LOW;
		}
		data = (data<<1);

		i2c_clock();
	}
	sda_in();
	i2c_clock();

	if ( SDA_PIN &(1<<SDA) ) {
		return 0;
	}

	return 1;
}


uint8_t soft_i2c_recieve_data_nack( void ) {
	uint8_t data = 0;

		sda_in();

		for ( uint8_t i = 0; i < 8; i++ ) {

			data = data << 1;

			if ( SDA_PIN &(1<<SDA) ) {
				data |= 0x01;
			}

			i2c_clock();
		}

		sda_out();
		SDA_HIGH;
		i2c_clock();


	return data;
}


uint8_t soft_i2c_recieve_data_ack( void ) {

	uint8_t data = 0;

		sda_in();

		for ( uint8_t i = 0; i < 8; i++ ) {
			data = data << 1;
			if ( SDA_PIN &(1<<SDA) ) {
				data |= 0x01;
			}

			i2c_clock();
		}

		sda_out();
		SDA_LOW;
		i2c_clock();


	return data;
}
